﻿using System;
using System.Diagnostics;
using System.IO;
using UnityEditor;
using UnityEngine;

public class ExpandToolsMenu
{
    readonly static CreateJson createJson = new CreateJson();
    static CreateClassWindow create = new CreateClassWindow();

    static string directory = "/Editor/EditorAssets";
    static string assetPath = "Assets{0}/{1}.asset";
    static double lastError;

    [MenuItem("Tools/GenerateCSScript", false, 2)]
    public static void GenerateCSScript()
    {
        SerializeConfig.Singleton.CollectPrefabRes(true);
    }

    [MenuItem("Tools/GenerateLuaScript", false, 2)]
    public static void GenerateLuaScript()
    {
        SerializeConfig.Singleton.CollectPrefabRes(false);
    }

    [MenuItem("GameObject/Generate/CreateCS", false, 0)]
    public static void CreateCS()
    {
        ExportScript(create, true);
    }

    [MenuItem("GameObject/Generate/CreateLua", false, 0)]
    public static void CreateLua()
    {
        ExportScript(create, false);
    }

    [MenuItem("GameObject/Generate/CreateJson", false, 0)]
    public static void CreateJson()
    {
        ExportScript(createJson, true);
    }

    [MenuItem("Tools/Build Execl Config", false, 5)]
    public static void BuildExeclConfig()
    {
        string frontPath = Application.dataPath;
        int tempPos = frontPath.IndexOf("Assets");
        string rootPath = frontPath.Substring(0, tempPos);

        string path = "Build_ExeclConfig.bat";
        Process proc = Process.Start(rootPath + path);
        proc.WaitForExit(); AssetDatabase.Refresh();
    }

    [MenuItem("Tools/Build Protobuf File", false, 5)]
    public static void BuildProtobufFile()
    {
        string frontPath = Application.dataPath;
        int tempPos = frontPath.IndexOf("Assets");
        string rootPath = frontPath.Substring(0, tempPos);

        string path = "Build_Protobuf.bat";
        Process proc = Process.Start(rootPath + path);
        proc.WaitForExit(); AssetDatabase.Refresh();
    }

    public static void CreateWindow(GameObject go, bool script)
    {
        create.CreateWindow(go, script);
    }

    public static void CreateWindow(GameObject go)
    {
        GUILayout.BeginHorizontal();
        if (GUILayout.Button("CreateCS"))
        {
            CreateWindow(go, true);
        }
        if (GUILayout.Button("CreateLua"))
        {
            CreateWindow(go, false);
        }

        if (GUILayout.Button("CreateJson"))
        {
            createJson.CreateWindow(go, true);
        }
        GUILayout.EndHorizontal();
    }

    public static void ExportScript(ICreateWindow create, bool script)
    {
        GameObject[] gameObjects = Selection.gameObjects;
        if (gameObjects.Length == 1)
        {
            create.CreateWindow(gameObjects[0], script);
        }
        else if (EditorApplication.timeSinceStartup - lastError < 1)
        {
            lastError = EditorApplication.timeSinceStartup;
        }
        else if (gameObjects.Length > 1)
        {
            EditorUtility.DisplayDialog("警告", "你只能选择一个GameObject", "确定");
            lastError = EditorApplication.timeSinceStartup;
        }
        else
        {
            EditorUtility.DisplayDialog("警告", "你必需选择一个GameObject", "确定");
            lastError = EditorApplication.timeSinceStartup;
        }
    }

    public static T GetAssetConfig<T>() where T : ScriptableObject
    {
        string tempPath = string.Format(assetPath, directory, typeof(T).Name);
        T assetScript = AssetDatabase.LoadAssetAtPath<T>(tempPath);

        if (assetScript == null)
        {
            assetScript = CreateAssetConfig<T>(directory);
        }
        return assetScript;
    }

    public static T CreateAssetConfig<T>(string path) where T : ScriptableObject
    {
        string directory = Application.dataPath + path;
        if (!Directory.Exists(directory))
        {
            Directory.CreateDirectory(directory);
        }

        T assetScript = ScriptableObject.CreateInstance<T>();
        string tempPath = string.Format(assetPath, path, typeof(T).Name);
        AssetDatabase.CreateAsset(assetScript, tempPath);

        AssetDatabase.Refresh();
        return assetScript;
    }

    public static Type GetExportType(string typeFullName)
    {
        var assemblys = AppDomain.CurrentDomain.GetAssemblies();
        foreach (var assembly in assemblys)
        {
            var type = assembly.GetType(typeFullName);
            if (type != null)
            {
                return type;
            }
        }
        return null;
    }
}

public class IScriptableObject<T> : ScriptableObject where T : ScriptableObject
{
    private static T Instance;

    public static T Singleton
    {
        get
        {
            if (Instance == null)
            {
                Instance = ExpandToolsMenu.GetAssetConfig<T>();
            }
            return Instance;
        }
    }
}